import Taro from "@tarojs/taro";
import { useState, useEffect } from "react";
import Node from "./index";
import {
  Block,
  Text,
  View,
  RichText,
  Image,
  Video,
  Audio,
} from "@tarojs/components";
import "./index.less";
const RichTextComponent = (props) => {
  const { n, i, opts, noop } = props;
  const [ctrl, setCtrl] = useState({});
  const [isIOS] = useState(Taro.getSystemInfoSync().system.includes("iOS"));

  useEffect(() => {
    props.onAdd && props.onAdd(props);
  }, []);

  const getNode = (target) => {
    try {
      const indices = target.split("_");
      let node = props.childs[indices[0]];
      for (let i = 1; i < indices.length; i++) {
        node = node.children[indices[i]];
      }
      return node;
    } catch (error) {
      return {
        text: "",
        attrs: {},
        children: [],
      };
    }
  };

  const play = (target) => {
    if (props.root) {
      props.root.triggerEvent("play");
      if (props.root.data.pauseVideo) {
        let found = false;
        const id = target.target.id;

        for (let i = props.root._videos.length - 1; i >= 0; i--) {
          if (props.root._videos[i].id === id) {
            found = true;
          } else {
            props.root._videos[i].pause();
          }
        }

        if (!found) {
          const videoContext = Taro.createVideoContext(id, this);
          videoContext.id = id;
          if (props.root.playbackRate) {
            videoContext.playbackRate(props.root.playbackRate);
          }
          props.root._videos.push(videoContext);
        }
      }
    }
  };

  const imgTap = (target) => {
    const node = getNode(target.target.dataset.i);

    if (node.a) {
      return linkTap(node.a);
    }

    if (!node.attrs.ignore) {
      props.root.triggerEvent("imgtap", node.attrs);
      if (props.root.data.previewImg) {
        const currentImg = props.root.imgList[node.i];
        Taro.previewImage({
          showmenu: props.root.data.showImgMenu,
          current: currentImg,
          urls: props.root.imgList,
        });
      }
    }
  };

  const imgLoad = (e) => {
    const i = e.target.dataset.i;
    const node = getNode(i);
    let width;
    if (node.w) {
      if ((props.opts[1] && !ctrl[i]) || ctrl[i] === -1) {
        width = 1;
      }
    } else {
      width = e.detail.width;
    }

    if (width) {
      setCtrl((prevCtrl) => ({ ...prevCtrl, [i]: width }));
      checkReady();
    }
  };

  const checkReady = () => {
    if (!props.root.data.lazyLoad) {
      props.root.imgList._unloadimgs -= 1;

      if (!props.root.imgList._unloadimgs) {
        setTimeout(() => {
          props.root
            .getRect()
            .then((rect) => {
              props.root.triggerEvent("ready", rect);
            })
            .catch(() => {
              props.root.triggerEvent("ready", {});
            });
        }, 350);
      }
    }
  };

  const linkTap = (t) => {
    const node = t.currentTarget ? getNode(t.currentTarget.dataset.i) : {};
    const attrs = node.attrs || t;
    const url = attrs.href;

    props.root.triggerEvent("linktap", {
      innerText: props.root.getText(node.children || []),
      ...attrs,
    });

    if (url) {
      if (url[0] === "#") {
        props.root.navigateTo(url.substring(1)).catch(() => {});
      } else if (url.split("?")[0].includes("://")) {
        if (props.root.data.copyLink) {
          Taro.setClipboardData({
            data: url,
            success: () =>
              Taro.showToast({
                title: "链接已复制",
              }),
          });
        }
      } else {
        Taro.navigateTo({
          url: url,
          fail: () => {
            Taro.switchTab({
              url: url,
              fail: () => {},
            });
          },
        });
      }
    }
  };

  const mediaError = (e) => {
    const i = e.target.dataset.i;
    const node = getNode(i);

    if (node.name === "video" || node.name === "audio") {
      let errorCount = (ctrl[i] || 0) + 1;
      if (errorCount > node.src.length) {
        errorCount = 0;
      }
      if (errorCount < node.src.length) {
        setCtrl((prevCtrl) => ({ ...prevCtrl, [i]: errorCount }));
      }
    } else if (node.name === "img") {
      if (props.opts[2]) {
        setCtrl((prevCtrl) => ({ ...prevCtrl, [i]: -1 }));
      }
      checkReady();
    }

    props.root &&
      props.root.triggerEvent("error", {
        source: node.name,
        attrs: node.attrs,
        errMsg: e.detail.errMsg,
      });
  };

  return (
    <Block>
      {n.name === "img" ? (
        <Block>
          {n.t ? (
            <RichText
              style={`display:${n.t}`}
              nodes={`<img class='_img' style='${n.attrs.style}' src='${n.attrs.src}'>`}
              data-i={i}
              onTap={imgTap}
            />
          ) : (
            <Block>
              {(opts[1] && !ctrl[i]) ||
                (ctrl[i] < 0 && (
                  <Image
                    className="_img"
                    style={n.attrs.style}
                    src={ctrl[i] < 0 ? opts[2] : opts[1]}
                    mode="widthFix"
                  />
                ))}

              <Image
                id={n.attrs.id}
                className={`_img ${n.attrs.class}`}
                style={`${ctrl[i] === -1 ? "display:none;" : ""}width:${
                  ctrl[i] || 1
                }px;height:1px;${n.attrs.style}`}
                src={n.attrs.src}
                mode={!n.h ? "widthFix" : !n.w ? "heightFix" : ""}
                lazy-load={opts[0]}
                webp={n.webp}
                show-menu-by-longpress={opts[3] && !n.attrs.ignore}
                data-i={i}
                bindload={imgLoad}
                binderror={mediaError}
                catchtap={imgTap}
                bindlongpress={noop}
              />
            </Block>
          )}
        </Block>
      ) : (
        <Block>
          {n.text ? (
            <Text
              user-select={`${opts[4] === "force" && isIOS ? "force" : "auto"}`}
              decode
            >
              {n.text}
            </Text>
          ) : null}
          {n.name === "br" ? <Text>{"\n"}</Text> : null}
          {n.name === "a" ? (
            <View
              id={n.attrs.id}
              className={`${n.attrs.href ? "_a " : ""}${n.attrs.class}`}
              hover-class="_hover"
              style={`display:inline;${n.attrs.style}`}
              data-i={i}
              onTap={linkTap}
            >
              <Node childs={n.children} opts={opts} style="display:inherit" />
            </View>
          ) : null}
          {n.name === "video" ? (
            <Video
              id={n.attrs.id}
              className={n.attrs.class}
              style={n.attrs.style}
              autoplay={n.attrs.autoplay}
              controls={n.attrs.controls}
              loop={n.attrs.loop}
              muted={n.attrs.muted}
              object-fit={n.attrs["object-fit"]}
              poster={n.attrs.poster}
              src={n.src[ctrl[i] || 0]}
              data-i={i}
              onTap={play}
              onError={mediaError}
            />
          ) : null}
          {n.name === "audio" ? (
            <Audio
              id={n.attrs.id}
              className={n.attrs.class}
              style={n.attrs.style}
              author={n.attrs.author}
              controls={n.attrs.controls}
              loop={n.attrs.loop}
              name={n.attrs.name}
              poster={n.attrs.poster}
              src={n.src[ctrl[i] || 0]}
              data-i={i}
              onPlay={play}
              onError={mediaError}
            />
          ) : null}
          {n.name !== "img" &&
          n.name !== "br" &&
          n.name !== "a" &&
          n.name !== "video" &&
          n.name !== "audio" ? (
            <RichText
              id={n.attrs.id}
              style={n.f}
              user-select={opts[4]}
              nodes={[n]}
            />
          ) : null}
        </Block>
      )}
    </Block>
  );
};

export default RichTextComponent;
